import java.awt.Frame;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.IOException;
import java.nio.FloatBuffer;

import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCanvas;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.glu.GLU;

import com.sun.opengl.util.Animator;
import com.sun.opengl.util.texture.TextureIO;
/*
 * Tomer Nuni 300585312
 * Idan Meshita 300043726
 */
public class PortalGame implements GLEventListener, KeyListener {
    float rotateT = 0.0f;
    static GLU glu = new GLU();
    static GLCanvas canvas = new GLCanvas();
    static Frame frame = new Frame("Jogl 3D Shape/Rotation");
    static Animator animator = new Animator(canvas);
    
   

	private LevelBuilder mapBuilder;
	private LevelBuilder mapBuilder2;
	

	private Navigation navigation;
	private PortalBullet portalBulleta ;
	private PortalBullet portalBulletb ;
	private Portal portal;
	private Switcher switcher;
	private Box box;
	private int level=1;
	
	float[] colorBlack  = {0.0f,0.0f,0.0f,1.0f};
	float[] colorWhite  = {1.0f,1.0f,1.0f,1.0f};
	float[] colorGray   = {0.6f,0.6f,0.6f,1.0f};
	float[] colorRed    = {1.0f,0.0f,0.0f,1.0f};
	float[] colorBlue   = {0.0f,0.0f,0.1f,1.0f};
	float[] colorYellow = {1.0f,1.0f,0.0f,1.0f};
	float[] colorLightYellow = {.5f,.5f,0.0f,1.0f};
	
	
	public PortalGame() {

		level=1;
		
		switcher = new Switcher();
		portal=new Portal();
		mapBuilder= new Level1Builder();
		mapBuilder2= new Level2Builder(switcher);

		navigation = new Navigation(portal,null);
		navigation.setMapBuilder(mapBuilder);
		
		portalBulleta= new PortalBullet(glu, portal, 1, 1,0, 1);
		portalBulletb= new PortalBullet(glu, portal, 0, 1,1,2);
		
		

		box= new Box(portal,switcher); 
		
	}

	public void level2(){
		level=2;

		portal.restartPortal();
		portalBulleta.portal=portal;
		portalBulletb.portal=portal;
		navigation = new Navigation(portal,switcher);
		navigation.setMapBuilder(mapBuilder2);
		
	}
    public void display(GLAutoDrawable gLDrawable) {
    	navigation.updatePersonPosition();
		final GL gl = gLDrawable.getGL();
		gl.glClear(GL.GL_COLOR_BUFFER_BIT);
		gl.glClear(GL.GL_DEPTH_BUFFER_BIT);
		gl.glLoadIdentity();
		//set the camera view
		//glu.gluLookAt(eyeX,eyeY,eyeZ,eyeX+(COS(beta)*COS(alpha)),eyeY+SIN(beta),eyeZ+(COS(beta)*SIN(alpha)),upX,upY,upZ);
		Point3D eye = navigation.getLocation().getEyePosition();
		Point3D lookAt = navigation.getLocation().getLookAtPoint();
		Point3D up = navigation.getLocation().getUpVector();
		
		glu.gluLookAt(eye.x,eye.y,eye.z,lookAt.x,lookAt.y,lookAt.z,up.x,up.y,up.z);
		if (level==1)
			mapBuilder.draw(gl);
		else
			mapBuilder2.draw(gl);
		portalBulleta.draw(gl);
		portalBulletb.draw(gl);
		portal.draw(gl);
		if (level==2){
			switcher.draw(gl);
			box.draw(gl);
		}

    }
 


    public void init(GLAutoDrawable gLDrawable) {
		GL gl = gLDrawable.getGL();
		initLight(gl);
		gl.glShadeModel(GL.GL_SMOOTH);
		gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
		gl.glClearDepth(1.0f);
		gl.glEnable(GL.GL_DEPTH_TEST);
		gl.glDepthFunc(GL.GL_LEQUAL);
		gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);
		//init texture
        gl.glEnable(GL.GL_TEXTURE_2D);
        loadTexture();
       
		mapBuilder.buildMap(gl);
		mapBuilder2.buildMap(gl);
		portalBulleta.buildBullet(gl);
		portalBulletb.buildBullet(gl);
		
		
			switcher.buildSwitch(gl);
			box.buildBox(gl);
		
		portal.buildPortal(gl);
		
		
/*
		tableBuilder.buildTable(gl);
		tableBuilder.buildTable(gl);
		bench1.buildTable(gl);
		bench2.buildTable(gl);*/
		gLDrawable.addKeyListener(this);
		
    }

    public void displayChanged(GLAutoDrawable gLDrawable, 
			       boolean modeChanged, boolean deviceChanged) {
    }
 
    private void loadTexture() {
    	 try {
     		String filename="wall.jpg"; // the FileName to open
     		mapBuilder.wallTexture=TextureIO.newTexture(new File( filename ),true);
     		mapBuilder2.wallTexture=TextureIO.newTexture(new File( filename ),true);
         } catch (IOException e) {
             e.printStackTrace();
             throw new RuntimeException(e);
         }
         try {
     		String filename="celling.jpg"; // the FileName to open
     		mapBuilder.cellingTexture=TextureIO.newTexture(new File( filename ),true);
     		mapBuilder2.cellingTexture=TextureIO.newTexture(new File( filename ),true);
     		
         } catch (IOException e) {
             e.printStackTrace();
             throw new RuntimeException(e);
         }
         try {
     		String filename="floor.jpg"; // the FileName to open
     		mapBuilder.floorTexture=TextureIO.newTexture(new File( filename ),true);
     		mapBuilder2.floorTexture=TextureIO.newTexture(new File( filename ),true);
         } catch (IOException e) {
             e.printStackTrace();
             throw new RuntimeException(e);
         }
         
	}

	public void reshape(GLAutoDrawable gLDrawable, int x, 
			int y, int width, int height) {
		GL gl = gLDrawable.getGL();
		if(height <= 0) {
		    height = 1;
		}
		float h = (float)width / (float)height;
		gl.glMatrixMode(GL.GL_PROJECTION);
		gl.glLoadIdentity();
		glu.gluPerspective(50.0f, h, 1.0, 10000.0);
		gl.glMatrixMode(GL.GL_MODELVIEW);
		gl.glLoadIdentity();
    }
 
    public void keyPressed(KeyEvent e) {
		if(e.getKeyCode() == KeyEvent.VK_ESCAPE) {
		    exit();
		}
		if(e.getKeyCode() =='W'||e.getKeyCode() =='w') {
			navigation.moveForward();
			if (level==2)
				switcher.checkActive(navigation.getLocation().getEyePosition(),1);

			if (level==1 && mapBuilder.checkDoorEnterance(navigation.getLocation().eyePosition))
			
				level2();
			if (level==2 && mapBuilder2.checkDoorEnterance(navigation.getLocation().eyePosition))
				
				exit();
				
			
		}
		if(e.getKeyCode() =='S'||e.getKeyCode() =='s') {
			navigation.moveBackward();
			if (level==2)
				switcher.checkActive(navigation.getLocation().getEyePosition(),1);
			
			if (level==1 && mapBuilder.checkDoorEnterance(navigation.getLocation().eyePosition))
				
				level2();
			if (level==2 && mapBuilder2.checkDoorEnterance(navigation.getLocation().eyePosition))
				
				exit();
		}
		if(e.getKeyCode() =='a'||e.getKeyCode() =='A') {
			
			navigation.moveLeft();
			if (level==2)
				switcher.checkActive(navigation.getLocation().getEyePosition(),1);
			if (level==1 && mapBuilder.checkDoorEnterance(navigation.getLocation().eyePosition))
				
				level2();
			if (level==2 && mapBuilder2.checkDoorEnterance(navigation.getLocation().eyePosition))
				
				exit();
		}
		if(e.getKeyCode() =='d'||e.getKeyCode() =='D') {
				navigation.moveRight();
				if (level==2)
					switcher.checkActive(navigation.getLocation().getEyePosition(),1);
				if (level==1 && mapBuilder.checkDoorEnterance(navigation.getLocation().eyePosition))
					level2();
				if (level==2 && mapBuilder2.checkDoorEnterance(navigation.getLocation().eyePosition))
					
					exit();
				
		}

		
		if(e.getKeyCode() ==KeyEvent.VK_UP) {
			navigation.moveHeadUp();
		}
		
		if(e.getKeyCode() ==KeyEvent.VK_DOWN) {
			navigation.moveHeadDown();
		}
		if(e.getKeyCode() == KeyEvent.VK_LEFT) {
			
			navigation.moveHeadLeft();
		}
		if(e.getKeyCode() == KeyEvent.VK_RIGHT) {
			
			navigation.moveHeadRight();
			
		}
		
		if (e.getKeyCode()==KeyEvent.VK_SPACE)
		{
			
			if (level==1)
				portalBulleta.shoot(navigation.getLocation().lookAtPoint,navigation.getLocation().eyePosition,mapBuilder);
			else
				portalBulleta.shoot(navigation.getLocation().lookAtPoint,navigation.getLocation().eyePosition,mapBuilder2);
		}
		if (e.getKeyCode()==KeyEvent.VK_CONTROL)
		{
			if (level==1)
				portalBulletb.shoot(navigation.getLocation().lookAtPoint,navigation.getLocation().eyePosition,mapBuilder);
			else
				portalBulletb.shoot(navigation.getLocation().lookAtPoint,navigation.getLocation().eyePosition,mapBuilder2);
		}
    }
 
    public void keyReleased(KeyEvent e) {
    }
 
    public void keyTyped(KeyEvent e) {
    }
 
    public static void exit(){
		animator.stop();
		frame.dispose();
		System.exit(0);
    }
 
    public static void main(String[] args) {
		canvas.addGLEventListener(new PortalGame());
		frame.add(canvas);
		frame.setSize(640, 480);
		
//		frame.setUndecorated(true);
//		frame.setExtendedState(Frame.MAXIMIZED_BOTH);
		frame.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
			    exit();
			}
		    });
		frame.setVisible(true);
		animator.start();
		canvas.requestFocus();
    }

    
    public void initLight( GL gl)
    {
      // First Switch the lights on.
      gl.glEnable( GL.GL_LIGHTING );
      gl.glDisable( GL.GL_LIGHT0 );
      gl.glEnable( GL.GL_LIGHT1 );
      

    

      
      float ambient[] =
	    { 0.0f, 0.0f, 0.0f, 1.0f };
	    float diffuse[] =
	    { 1.0f, 1.0f, 1.0f, 1.0f };
	    float specular[] =
	    { 1.0f, 1.0f, 1.0f, 1.0f };
	    float position[] =
	    { 0.0f, 0.0f, 0.0f, 1.0f };
	    float lmodel_ambient[] =
	    { 0.4f, 0.4f, 0.4f, 1.0f };
	    float local_view[] =
	    { 0.0f };

	    gl.glEnable(GL.GL_DEPTH_TEST);
	    gl.glDepthFunc(GL.GL_LESS);
	    
//	    gl.glShadeModel(GL.GL_SMOOTH);

	    gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, ambient, 0);
	    gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, diffuse, 0);
	    gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, position, 0);
	    gl.glLightModelfv(GL.GL_LIGHT_MODEL_AMBIENT, lmodel_ambient, 0);
	    gl.glLightModelfv(GL.GL_LIGHT_MODEL_LOCAL_VIEWER, local_view, 0);

	    gl.glEnable(GL.GL_LIGHTING);
	    gl.glEnable(GL.GL_LIGHT0);

	    gl.glClearColor(0.0f, 0.1f, 0.1f, 0.0f);

		

				
		gl.glEnable(GL.GL_LIGHT1);
		gl.glShadeModel(GL.GL_SMOOTH);
		gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
		gl.glClearDepth(1.0f);
		gl.glEnable(GL.GL_DEPTH_TEST);
		gl.glDepthFunc(GL.GL_LEQUAL);
		gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);
      
      }

}


